#include <stdio.h>
#include <stdlib.h>
#include "stack.h"

#define STRLEN 256
#define IN_LINE 1
#define IN_MULTILINE 2
#define IN_SINGLE_STRING 3
#define IN_DOUBLE_STRING 4
#define OUT 0
#define TRUE 1
#define FALSE 0
#define BRACKETS 1
#define PARENTHESES 2

int check_syntax(FILE *fp);

int main(int argc, char *argv[]){
    FILE *fp;
    int bad_line;

	if (argc < 2){
	    printf("Usage is syntax [FILE]");
	    exit(EXIT_FAILURE);
	}

	if( (fp=fopen(argv[1], "r")) == NULL)
        exit(EXIT_FAILURE);

    bad_line = check_syntax(fp);

    fclose(fp);

    if(bad_line)
        printf("Error on line %d", bad_line);
    else
        printf("syntax correct");

	exit(EXIT_SUCCESS);
}

int check_syntax(FILE *fp){
	STACK *stack;

	char cp, nextc;
	int state, ln, opened_braces;
	int error;

    stack = (STACK *)malloc(sizeof stack);

	state = OUT;
	ln  = 1;
	error = FALSE;
	opened_braces = 0;

	while( (cp = fgetc(fp)) != EOF){
		//check for comments first
		if(cp == '/'){
			if( nextc == '/'){ //we're in a single line comment
				while( (cp = fgetc(fp)) != EOF && cp != '\n')
                    ;
                ln++;
			}
			if(nextc == '*'){ //we're in a multi line comment
				while( (cp = getc(fp)) != EOF && (cp != '*' && (nextc = fgetc(fp)) != '/'))
                    ungetc(nextc, fp);
                ungetc(nextc, fp);
			}

		}

        //check for double quotes string
        if(cp == '\"'){
            while( (cp=fgetc(fp)) != EOF && cp != '\"')
                if(cp == '\\' && ( (nextc = fgetc(fp)) == '\"'))
                   ;
        }

        //check for single quotes string
        if(cp == '\''){
            while( (cp=fgetc(fp)) != EOF && cp != '\'')
                if(cp == '\\' && ( (nextc = fgetc(fp)) == '\''))
                ;
        }
		//we are out of a comment, time to check some syntax!
        switch(cp){
            case '\n':
                ln++;
                break;
            case '{':
                if(stack->state != OUT)
                    error = TRUE;
                opened_braces++;
                break;
            case '}':
                if(stack->state != OUT || opened_braces < 1)
                    error = TRUE;
                opened_braces--;
                break;
            case '(':
                stack = add_to_stack(stack, PARENTHESES);
                break;
            case ')':
                if(stack->state != PARENTHESES)
                    error = TRUE;
                stack = pop_stack(stack);
                break;
            case '[':
                stack = add_to_stack(stack, BRACKETS);
                break;
            case ']':
                if(stack->state != BRACKETS)
                    error = TRUE;
                stack = pop_stack(stack);
                break;
        }
        if(error == TRUE){
            printf("bracket/parentheses missmatch around line %d\n", cp, ln);
            return(ln);
        }
	}
	if(opened_braces != 0){
	    printf("Unclosed Braces around line %d\n", ln);
        return(ln);
	}
	return(0);
}


